/*
 * @Description: 字符串协议解构
 * @Version: 1.0
 * @Autor: lzc
 * @Date: 2021-09-15 14:12:03
 * @LastEditors: lzc
 * @LastEditTime: 2021-09-15 16:40:09
 */
#include "command_parse.h"

static Cmd_Info_Type s_cmd_info;
static myCmd_Info_Type s_my_cmd_info;

static uint8_t start(myCmd_Info_Type info)
{
    return MS_EOK;
}
_MSG_FUN(start, "0");

static uint8_t end(myCmd_Info_Type info)
{
    return MS_EOK;
}
_MSG_FUN(end, "0.end");

static myCmd_Info_Type s_my_cmd_info;
/**
 * @function: communicate_split
 * @brief: 字符串切割（旧）
 * @param {constchar} *data
 * @param {Cmd_Info_Type} *info_buf
 * @return {*}
 * @author: lzc
 */
char communicate_split(const char *data, Cmd_Info_Type *info_buf)
{
    uint8_t position = 0;
    uint8_t cmd_num = 0;
    uint8_t cmd_len = 0;
    uint8_t data_num = 0;
    uint8_t len = 0;
    uint8_t get_cmd_flag = 0;
    const char *ptr;

    memset(info_buf, 0, sizeof(Cmd_Info_Type));
    len = strlen(data) + 1;
    ptr = data;
    if (*ptr == '*')
    {
        ptr++;
        len--;
    }
    while (position < len)
    {
        switch (get_cmd_flag)
        {
        case 0:
            info_buf->cmd[cmd_num][cmd_len] = *ptr;
            if (cmd_len++ >= (MSG_CMD_LEN - 1))
            {
                info_buf->cmd[cmd_num][cmd_len] = '\0';
                get_cmd_flag = 1;//一个命令只接受三个字符
            }
            else if (*(ptr + 1) == '[')
            {
                ptr++;
                get_cmd_flag = 2;
                cmd_len = 0;
            }
            break;
        case 1:
            if (*ptr == ' ')
            {
                get_cmd_flag = 0;
                cmd_num++;
                cmd_len = 0;
                if (cmd_num >= MSG_MAX_ARGS) //命令太多
                {
                    return 3;
                }
            }
            else if (*ptr == '[')
            {
                get_cmd_flag = 2;
                cmd_len = 0;
            }
            else if (*ptr == '\0')
            {
                return 0;
            }
            break;
        case 2://参数
            if (*ptr == ']')
            {
                if (*(ptr + 1) == '\0') //结束
                {
                    info_buf->data[data_num][cmd_len] = '\0';
                    return 0;
                }
                else if (*(ptr + 1) == ' ')
                {
                    ptr++;
                    get_cmd_flag = 0;
                    cmd_num++;
                    cmd_len = 0;
                    data_num++;
                    if (cmd_num >= MSG_MAX_ARGS) //命令太多
                    {
                        return 3;
                    }
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                info_buf->data[data_num][cmd_len] = *ptr;
                if (cmd_len++ >= (MSG_ARG_LEN - 1))
                {
                    info_buf->data[data_num][cmd_len] = '\0';
                    return 3;//参数太长
                }
            }
            break;
        }
        ptr++;
        position++;
    }
    return 0;
}

/**
 * @function: communicate_parse
 * @brief:字符串解析（旧）
 * @param {constchar} *data
 * @return {*}
 * @author: lzc
 */
int communicate_parse(const char *data)
{
    char err;
    char i, j;
    memset((uint8_t *)&s_cmd_info, 0, sizeof(Cmd_Info_Type));
    err = communicate_split(data, &s_cmd_info);
    if (err != 0)
    {
        MSG_OUTPUT("error! msg isn't legal !\n");
        return -1;
    }
    for (i = 0; i < MSG_COUNT; i++)
    {
        /*匹配命令1*/
        if (strcmp(s_cmd_buf[i][0], (const char *)s_cmd_info.cmd[0]) == 0)
        {
            for (j = 1; j < MSG_MAX_ARGS; j++)
            {
                if (strcmp(s_cmd_buf[i][j], (const char *)s_cmd_info.cmd[j]) == 0)
                {
                    if ((j + 1) >= MSG_MAX_ARGS)
                    {
                        /*匹配成功,执行对应函数*/
                        cmd_deal_port[i](s_cmd_info);
                        return 0;
                    }
                }
                else
                {
                    break;
                }
            }
        }
    }
    /*匹配失败*/
    MSG_OUTPUT("error! unknown command!\n");
    return -1;
}


/**
 * @function: msg_split
 * @brief: 字符分割
 * @param {constchar} *data
 * @param {myCmd_Info_Type} *info_buf
 * @return {*}
 * @author: lzc
 */
char old_temp_data = '1';
static int msg_split(const char *data, myCmd_Info_Type *info_buf)
{
    uint8_t position = 0;
    uint8_t cmd_num = 0;
    uint8_t cmd_len = 0;
    uint8_t cmd_position = 0;
    uint8_t data_num = 0;
    uint8_t data_len = 0;
    uint8_t msg_len = 0;
    uint8_t get_cmd_step = 0;
    const char *ptr;

    memset(info_buf, 0, sizeof(myCmd_Info_Type));
    msg_len = strlen(data) + 1;
    ptr = data;

    while (position < msg_len)
    {
        switch (get_cmd_step)
        {
        case 0: //命令
            info_buf->cmd[cmd_len] = *ptr;
            cmd_len++;
            if (cmd_len - cmd_position - 1 >= MSG_CMD_LEN)
            {
                info_buf->cmd[cmd_len] = '_';
                cmd_position = cmd_len;
                get_cmd_step = 1;//一个命令只接受三个字符
                break;
            }
            if (*(ptr + 1) == '[')
            {
                info_buf->cmd[cmd_len] = '_';
                cmd_position = cmd_len;
                ptr++;
                get_cmd_step = 2;
            }
            else if (*(ptr + 1) == ' ')
            {
                info_buf->cmd[cmd_len] = '_';
                cmd_position = cmd_len;
                get_cmd_step = 1;//一个命令只接受三个字符
            }
            else if (*(ptr + 1) == '\0')
            {
                info_buf->cmd[cmd_len] = '\0';
                get_cmd_step = 1;//一个命令只接受三个字符
            }
            break;
        case 1://忽略部分
            if (*ptr == ' ')
            {
                get_cmd_step = 0;
                cmd_num++;
                cmd_len++;
                if (cmd_num >= MSG_MAX_ARGS) //命令太多
                {
                    return MS_EFULL;
                }
            }
            else if (*ptr == '[')
            {
                // 蓝牙接收数据错误的处理
                // 没有接收到数据区 即 get history[]
                if (*(ptr + 1) == ']')
                {
                    get_cmd_step = 2; data_len = 0;
                    info_buf->data[data_num][data_len] = old_temp_data + 1;
                    data_len ++;
                }
                else
                {
                    get_cmd_step = 2;
                    data_len = 0;
                }
            }
            else if (*ptr == '\0')
            {
                info_buf->cmd[cmd_len] = '\0';
                return MS_EOK;
            }
            // 蓝牙接收数据错误的处理
            // 没有接收到数据区 即 get historyx]
            else if (*(ptr) >= '0' && *(ptr) <= '9')
            {
                get_cmd_step = 2; data_len = 0;
                info_buf->data[data_num][data_len] = *ptr;
                data_len ++;
            }
            break;
        case 2://参数
            // 右方括号
            if (*ptr == ']')
            {
                if (*(ptr + 1) == '\0') //结束
                {
                    info_buf->data[data_num][data_len] = '\0';
                    info_buf->cmd[cmd_len] = '\0';
                    return MS_EOK;
                }
                else if (*(ptr + 1) == ' ')
                {
                    ptr++;
                    get_cmd_step = 0;
                    cmd_num++;
                    cmd_len++;
                    data_len = 0;
                    data_num++;
                    if (cmd_num >= MSG_MAX_ARGS) //命令太多
                    {
                        return MS_EFULL;
                    }
                }
                else
                {
                    //多接受一条蓝牙数据，清除对应数据源
                    // memset((void *)g_uart_buffer.g_uart_buffer, 0, sizeof(&g_uart_buffer.g_uart_buffer));
                    return MS_EOK;
                }
            }
            // 左方括号 以及 数据
            else
            {
                // 先判断是否是数字
                if (*(ptr) >= '0' && *(ptr) <= '9')
                {
                    old_temp_data = *(ptr);
                }
                info_buf->data[data_num][data_len] = *ptr;
                if (data_len++ >= (MSG_ARG_LEN - 1))
                {
                    info_buf->data[data_num][data_len] = '\0';
                    return MS_EFULL;//参数太长
                }
            }
            break;
        }
        ptr++;
        position++;
    }
    return MS_EOK;
}

/**
 * @function: msg_parse
 * @brief: msg消息解析
 * @param {const char *data}
 * @return {*}
 * @author: lzc
 */
// DONE:验证全部指令，全部都可以。
int msg_parse(const char *data)
{
    char err;
    uint8_t s_my_cmd_info_lens = 0;
    const _init_msg *init_msg_p = NULL;
    memset((uint8_t *)&s_my_cmd_info, 0, sizeof(myCmd_Info_Type));
    err = msg_split(data, &s_my_cmd_info);
    s_my_cmd_info_lens = strlen((const char *)s_my_cmd_info.cmd);
    if (s_my_cmd_info.cmd[s_my_cmd_info_lens - 1] == '_')
        s_my_cmd_info.cmd[s_my_cmd_info_lens - 1] = 0x00;
    if (err != MS_EOK)
    {
        MSG_OUTPUT("err! msg isn't legal !\n");
        return -1;
    }
    // 接收处理
    for (init_msg_p = &_imp_start; init_msg_p < &_imp_end; init_msg_p++)
    {
        if (s_my_cmd_info.cmd[0] == '*') //此处是进行获取版本号以及设备类型的兼容
        {
            for (int i = 0; i < 4; i++)
            {
                s_my_cmd_info.cmd[i] = s_my_cmd_info.cmd[i + 1];
            }
        }
        // 完整性判断
        if (strcmp((const char *)(init_msg_p->name), (const char *)(&s_my_cmd_info.cmd[0])) == 0)
        {
            init_msg_p->msg_port_fun(s_my_cmd_info);
            MSG_OUTPUT("\n");//## \n
            return MS_EOK;
        }
    }
    //错误命令，需要抛弃.返回上次的数据
    //if (strcmp((const char *)(init_msg_p->name), (const char *)(&s_cmd_info.cmd[0])) != 0)
    //{
    //    return MS_EOK;
    //}
    return MS_EOK;
}

